#pragma onec

#include <iostream>
using namespace std;
#include <unistd.h>
#include <pthread.h>
#include <string>
#include <vector>
#include <semaphore.h>

const int CAP = 8;


template<class T>
class RingQueue
{
  private:
    vector<T> _q;
    int _cap; // 容量大小
    int _p_pos; // 生产者位置
    int _c_pos; // 消费者位置 
    sem_t _blank_sem; // 空间信号量
    sem_t _data_sem; // 数据信号量 
  private:
    void P(sem_t& s)
    {
      sem_wait(&s);
    }
    void V(sem_t& s)
    {
      sem_post(&s);
    }
  public:
    RingQueue(int num = CAP)
      :_cap(CAP),
      _p_pos(0),
      _c_pos(0)
    {
      _q.resize(CAP);
      sem_init(&_blank_sem , 0 , _cap);
      sem_init(&_data_sem , 0 , _cap);
    }

    ~RingQueue()
    {
      sem_destroy(&_blank_sem);
      sem_destroy(&_data_sem);
    }

    void Push(const T& data)
    {
      this->P(_blank_sem);
      _q[_p_pos] = data;
      this->V(_data_sem);

      // 下一次生产的位置
      _p_pos++;
      _p_pos %= _cap;
    }

    void Pop(T& data)
    {
      this->P(_data_sem);
      data = _q[_c_pos];
      this->V(_blank_sem);

      // 下一次消费的位置
      _c_pos++;
      _c_pos %= _cap;
    }

};

